﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace DiscreteEventModel.Common {

    public abstract class Finalizable {

        private volatile IFinalizer<Finalizable> _finalizer;

        ~Finalizable() {
            if(this._finalizer != null) {
                IFinalizer<Finalizable> finalizer = this._finalizer;
                this._finalizer = null;

                if(!finalizer.TryFinalize(this) && this._finalizer == null) {
                    this._finalizer = finalizer;
                }

                if(this._finalizer != null) {
                    GC.ReRegisterForFinalize(this);
                }
            }
        }

        public IFinalizer<Finalizable> Finalizer {
            get {
                return this._finalizer;
            }
            set {
                if(value == null) {
                    if(this._finalizer != null) {
                        GC.SuppressFinalize(this);
                        this._finalizer = null;
                    }
                } else if(value != this._finalizer && value.CanFinalize(this)) {
                    if(this._finalizer == null) {
                        GC.ReRegisterForFinalize(this);
                    }
                    this._finalizer = value;
                }
            }
        }

        protected Finalizable(IFinalizer<Finalizable> finalizer = null) {
            if(finalizer == null) {
                GC.SuppressFinalize(this);
            } else if(finalizer.CanFinalize(this)) {
                this._finalizer = finalizer;
            } else {
                throw new Exception();
            }
        }
    }
}
